from django.shortcuts import render
from QQLoginTool.QQtool import OAuthQQ
# Create your views here.
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView

# 请求方式： GET/oauth/qq/statues/
from meiduo import settings
from oauth.models import OAuthQQUser
from oauth.serializers import QQAuthUserSerializer
from oauth.utils import generate_access_token


class QQAuthURLView(APIView):
    # 获取请求地址，这个接口不需要前端传任何参数，所以为ｇｅｔ请求
    def get(self, request):
        # login_url ='https://graph.qq.com/oauth2.0/authorize?response_type=code&redirect_uri=http%3A%2F%2Fwww.meiduo.site%3A8080%2Foauth_callback.html&state=%2F&client_id=101474184'
        # 初始化OAuthQQ对象
        state = '/'
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI, state=state)

        # 获取QQ登录扫码页面，扫码后得到AuthorizationCode
        login_url = oauth.get_qq_url()

        return Response({"login_url": login_url})


"""
需要前端将获取到的code，返回到这个接口
拿到code后，换取access_token
再拿access_token换取ｏｐｅｎｉｄ
"""


# 请求方式GET / oauth / qq / users /?code = xxx
# 获取　access_token
class QQAuthUserView(APIView):
    def get(self, request):
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                        client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI)

        code = request.query_params.get('code')

        if not code:
            return Response({'message': '缺少code'}, status=status.HTTP_400_BAD_REQUEST)
        try:
            # 使用code向QQ服务器请求access_token
            # # 通过AuthorizationCode获取AccessToken
            access_token = oauth.get_access_token(code)
            # # 通过AccessToken获取OpenID
            openid = oauth.get_open_id(access_token)
        except Exception:
            return Response({'message': 'QQ服务异常'}, status=status.HTTP_503_SERVICE_UNAVAILABLE)

        # 当获取当openid时，要判断用户是否绑定过，若绑定过，则直接返回首页，若没有绑定则直接返回首页
        try:
            oauth_user = OAuthQQUser.objects.get(openid=openid)
        except OAuthQQUser.DoesNotExist:
            # ，创建用户并绑定到openid
            # 为了能够在后续的绑定用户操作中前端可以使用openid，在这里将openid签名后响应给前端
            # 对ｏｐｅｎｉｄ进行加密
            openid = generate_access_token(openid)
            return Response({"access_token": openid})

        else:
            # 如果没有发生异常则说明用户绑定过
            # 如果用户已经绑定过了则直接生成jwt　token ,
            # 返回jwt token 和　用户信息并跳转到首页

            # 获取oauth_user关联的user
            user = oauth_user.user
            # 生成jwt token
            from rest_framework_jwt.settings import api_settings
            # 获取这俩个方法
            jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
            jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
            # payload获取ｕｓｅｒ的信息，并编码生成ｔｏｋｅｎ
            payload = jwt_payload_handler(user)
            token = jwt_encode_handler(payload)

            response = Response({
                'token': token,
                'user_id': user.id,
                'username': user.username
            })

            return response

    """
    当用户填写完绑定信息后，
    前端需要把　用户的手机，短信验证码，处理过的openid,用户密码　返回
    １　接收参数
    ２　校验短信验证码，处理过得ｏｐｅｎｉｄ
    ３　根据手机号判断用户是否存在，若不存在，
        则会将手机号作为用户名为用户创建一个美多账户，并绑定用户，
        若存在，则判断密码跟之前的是否一致，不一致则返回，一致则直接绑定
    ４　保存数据
    5 返回响应

    请求方式 POST /oauth/qq/users/
    """

    def post(self, request):
        data = request.data

        serializer = QQAuthUserSerializer(data=data)

        serializer.is_valid(raise_exception=True)

        qquser = serializer.save()

        # 生成jwt token
        from rest_framework_jwt.settings import api_settings
        # 获取这俩个方法
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        # payload获取ｕｓｅｒ的信息，并编码生成ｔｏｋｅｎ
        payload = jwt_payload_handler(qquser.user)
        token = jwt_encode_handler(payload)

        response = Response({
            'token': token,
            'user_id': qquser.user.id,
            'username': qquser.user.username
        })

        return response



